package com.github.digital_wonderland.sling_metrics.filter;
import com.codahale.metrics.Timer;
import com.github.digital_wonderland.sling_metrics.service.MetricService;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.sling.SlingFilter;
import org.apache.felix.scr.annotations.sling.SlingFilterScope;
import org.apache.sling.api.SlingHttpServletRequest;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import java.io.IOException;
@SlingFilter(scope = SlingFilterScope.COMPONENT,
order = -10000,
metatype = true,
label = "Sling Metrics :: Component Filter",
description = "Sling Components Filter which generates Metrics for Components")
public class ComponentFilter implements javax.servlet.Filter {
private static final Logger LOG = LoggerFactory.getLogger(ComponentFilter.class);
@Property(label = "Enabled", boolValue = true, description = "Should the filter be enabled")
private static final String COMPONENT_FILTER_ENABLED = "componentFilter.enabled";
@Property(label = "Component Whitelist", value = ".*", description = "Regular expression to filter events by white listing on the resource type")
private static final String COMPONENT_FILTER_WHITELIST= "componentFilter.whitelist";
@Reference
protected MetricService metricService;
private boolean isEnabled = false;
private String whitelist = ".*";
@Activate
protected void activate(final ComponentContext context) {
isEnabled = (Boolean) context.getProperties().get(COMPONENT_FILTER_ENABLED);
whitelist = (String) context.getProperties().get(COMPONENT_FILTER_WHITELIST);
LOG.debug("ComponentFilter.isEnabled: [{}]", isEnabled);
}
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
LOG.debug("ComponentFilter init()");
}
@Override
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
LOG.debug("ComponentFilter doFilter()");
if(isEnabled && metricService.isEnabled()) {
if(servletRequest instanceof SlingHttpServletRequest) {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) servletRequest;
final String resourceType = slingRequest.getResource().getResourceType();
final String metricName = normalizeResourceType(resourceType);
if(metricName.matches(whitelist)) {
final Timer.Context context = metricService.timer(metricName).time();
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
context.stop();
}
}
} else {
LOG.error("Metrics ComponentFilter got called for non SlingHttpServletRequest");
}
}
}
private String normalizeResourceType(final String resourceType) {
return ("components." + resourceType).replaceAll("[\\./:]+", ".");
}
@Override
public void destroy() {
LOG.debug("ComponentFilter destroy()");
}
}